//! 类型转换系统
//!
//! 设计原则：
//! - 支持自动类型转换（隐式转换）
//! - 支持显式类型转换（强制转换）
//! - 提供类型转换规则管理
//! - 支持自定义转换函数
//! - 遵循墨言语言类型系统的转换规则

use crate::interpreter::method::MethodType;
use crate::interpreter::value::{Value, ValueData};
use std::collections::HashMap;
use std::sync::Arc;

/// 转换类型枚举
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ConversionType {
    /// 自动转换（隐式）
    Automatic,
    /// 显式转换（强制）
    Explicit,
}

/// 转换规则
#[derive(Clone)]
pub struct ConversionRule {
    /// 源类型
    pub from_type: MethodType,
    /// 目标类型
    pub to_type: MethodType,
    /// 转换类型（自动/显式）
    pub conversion_type: ConversionType,
    /// 转换函数
    pub converter: Arc<dyn Fn(&Value) -> Result<Value, String> + Send + Sync>,
    /// 转换优先级（数字越大优先级越高）
    pub priority: u32,
    /// 是否允许精度损失
    pub allow_precision_loss: bool,
    /// 转换描述
    pub description: String,
}

/// 类型转换管理器
pub struct TypeConverter {
    /// 转换规则映射： (源类型, 目标类型) -> 转换规则
    conversion_rules: HashMap<(MethodType, MethodType), ConversionRule>,
    /// 自定义转换函数
    custom_converters: HashMap<String, Arc<dyn Fn(&Value) -> Result<Value, String> + Send + Sync>>,
}

impl TypeConverter {
    /// 创建新的类型转换器
    pub fn new() -> Self {
        let mut converter = Self {
            conversion_rules: HashMap::new(),
            custom_converters: HashMap::new(),
        };

        // 注册默认转换规则
        converter.register_default_rules();
        converter
    }

    /// 注册默认转换规则
    fn register_default_rules(&mut self) {
        // 数字 -> 字符串
        self.register_conversion(
            MethodType::Number,
            MethodType::String,
            ConversionType::Automatic,
            Arc::new(|value| {
                if let ValueData::Number(n) = &value.data {
                    Ok(Value::string(n.to_string()))
                } else {
                    Err("需要数字值".to_string())
                }
            }),
            100,
            false,
            "数字转换为字符串",
        );

        // 字符串 -> 数字
        self.register_conversion(
            MethodType::String,
            MethodType::Number,
            ConversionType::Explicit,
            Arc::new(|value| {
                if let ValueData::String(s) = &value.data {
                    match s.parse::<f64>() {
                        Ok(n) => Ok(Value::number(n)),
                        Err(_) => {
                            // 尝试中文数字转换
                            Self::chinese_to_number(s)
                        }
                    }
                } else {
                    Err("需要字符串值".to_string())
                }
            }),
            90,
            true,
            "字符串转换为数字",
        );

        // 数字 -> 布尔值
        self.register_conversion(
            MethodType::Number,
            MethodType::Boolean,
            ConversionType::Automatic,
            Arc::new(|value| {
                if let ValueData::Number(n) = &value.data {
                    Ok(Value::boolean(*n != 0.0))
                } else {
                    Err("需要数字值".to_string())
                }
            }),
            95,
            false,
            "数字转换为布尔值",
        );

        // 布尔值 -> 数字
        self.register_conversion(
            MethodType::Boolean,
            MethodType::Number,
            ConversionType::Automatic,
            Arc::new(|value| {
                if let ValueData::Boolean(b) = &value.data {
                    Ok(Value::number(if *b { 1.0 } else { 0.0 }))
                } else {
                    Err("需要布尔值".to_string())
                }
            }),
            95,
            false,
            "布尔值转换为数字",
        );

        // 字符串 -> 布尔值
        self.register_conversion(
            MethodType::String,
            MethodType::Boolean,
            ConversionType::Automatic,
            Arc::new(|value| {
                if let ValueData::String(s) = &value.data {
                    Ok(Value::boolean(!s.is_empty()))
                } else {
                    Err("需要字符串值".to_string())
                }
            }),
            85,
            false,
            "字符串转换为布尔值",
        );

        // 布尔值 -> 字符串
        self.register_conversion(
            MethodType::Boolean,
            MethodType::String,
            ConversionType::Automatic,
            Arc::new(|value| {
                if let ValueData::Boolean(b) = &value.data {
                    let result = if *b { "真" } else { "假" };
                    Ok(Value::string(result.to_string()))
                } else {
                    Err("需要布尔值".to_string())
                }
            }),
            95,
            false,
            "布尔值转换为字符串",
        );

        // null -> 各种类型
        self.register_conversion(
            MethodType::Null,
            MethodType::String,
            ConversionType::Automatic,
            Arc::new(|value| {
                if let ValueData::Null = &value.data {
                    Ok(Value::string("无".to_string()))
                } else {
                    Err("需要null值".to_string())
                }
            }),
            80,
            false,
            "null转换为字符串",
        );

        self.register_conversion(
            MethodType::Null,
            MethodType::Number,
            ConversionType::Automatic,
            Arc::new(|value| {
                if let ValueData::Null = &value.data {
                    Ok(Value::number(0.0))
                } else {
                    Err("需要null值".to_string())
                }
            }),
            80,
            false,
            "null转换为数字",
        );

        self.register_conversion(
            MethodType::Null,
            MethodType::Boolean,
            ConversionType::Automatic,
            Arc::new(|value| {
                if let ValueData::Null = &value.data {
                    Ok(Value::boolean(false))
                } else {
                    Err("需要null值".to_string())
                }
            }),
            80,
            false,
            "null转换为布尔值",
        );

        // 列表 -> 字符串
        self.register_conversion(
            MethodType::List,
            MethodType::String,
            ConversionType::Explicit,
            Arc::new(|value| {
                if let ValueData::List(list) = &value.data {
                    let items: Vec<String> = list.borrow().iter().map(|v| v.to_string()).collect();
                    Ok(Value::string(format!("[{}]", items.join(", "))))
                } else {
                    Err("需要列表值".to_string())
                }
            }),
            70,
            false,
            "列表转换为字符串",
        );

        // 字典 -> 字符串
        self.register_conversion(
            MethodType::Dict,
            MethodType::String,
            ConversionType::Explicit,
            Arc::new(|value| {
                if let ValueData::Dict(dict) = &value.data {
                    let pairs: Vec<String> = dict
                        .borrow()
                        .iter()
                        .map(|(k, v)| format!("{}: {}", k, v.to_string()))
                        .collect();
                    Ok(Value::string(format!("{{{}}}", pairs.join(", "))))
                } else {
                    Err("需要字典值".to_string())
                }
            }),
            70,
            false,
            "字典转换为字符串",
        );
    }

    /// 注册转换规则
    pub fn register_conversion(
        &mut self,
        from_type: MethodType,
        to_type: MethodType,
        conversion_type: ConversionType,
        converter: Arc<dyn Fn(&Value) -> Result<Value, String> + Send + Sync>,
        priority: u32,
        allow_precision_loss: bool,
        description: &str,
    ) {
        let rule = ConversionRule {
            from_type: from_type.clone(),
            to_type: to_type.clone(),
            conversion_type,
            converter,
            priority,
            allow_precision_loss,
            description: description.to_string(),
        };

        self.conversion_rules.insert((from_type, to_type), rule);
    }

    /// 注册自定义转换函数
    pub fn register_custom_converter(
        &mut self,
        name: &str,
        converter: Arc<dyn Fn(&Value) -> Result<Value, String> + Send + Sync>,
    ) {
        self.custom_converters.insert(name.to_string(), converter);
    }

    /// 自动转换（隐式转换）
    pub fn convert_automatically(
        &self,
        value: &Value,
        target_type: &MethodType,
    ) -> Result<Value, String> {
        self.convert_with_type(value, target_type, ConversionType::Automatic)
    }

    /// 显式转换（强制转换）
    pub fn convert_explicitly(
        &self,
        value: &Value,
        target_type: &MethodType,
    ) -> Result<Value, String> {
        self.convert_with_type(value, target_type, ConversionType::Explicit)
    }

    /// 根据转换类型进行转换
    fn convert_with_type(
        &self,
        value: &Value,
        target_type: &MethodType,
        conversion_type: ConversionType,
    ) -> Result<Value, String> {
        let current_type = value.get_type();

        // 如果类型相同，直接返回
        if current_type == *target_type {
            return Ok(value.clone());
        }

        // 查找转换规则
        if let Some(rule) = self
            .conversion_rules
            .get(&(current_type.clone(), target_type.clone()))
        {
            // 检查转换类型是否匹配
            if rule.conversion_type == conversion_type
                || conversion_type == ConversionType::Explicit
            {
                return (rule.converter)(value);
            }
        }

        // 尝试自定义转换
        let converter_name = format!("{:?}_to_{:?}", current_type, target_type);
        if let Some(converter) = self.custom_converters.get(&converter_name) {
            return converter(value);
        }

        Err(format!(
            "无法将类型 {:?} 转换为 {:?} (转换类型: {:?})",
            current_type, target_type, conversion_type
        ))
    }

    /// 检查是否支持自动转换
    pub fn supports_automatic_conversion(
        &self,
        from_type: &MethodType,
        to_type: &MethodType,
    ) -> bool {
        if let Some(rule) = self
            .conversion_rules
            .get(&(from_type.clone(), to_type.clone()))
        {
            rule.conversion_type == ConversionType::Automatic
        } else {
            false
        }
    }

    /// 检查是否支持显式转换
    pub fn supports_explicit_conversion(
        &self,
        from_type: &MethodType,
        to_type: &MethodType,
    ) -> bool {
        self.conversion_rules
            .contains_key(&(from_type.clone(), to_type.clone()))
            || self
                .custom_converters
                .contains_key(&format!("{:?}_to_{:?}", from_type, to_type))
    }

    /// 获取转换规则
    pub fn get_conversion_rule(
        &self,
        from_type: MethodType,
        to_type: MethodType,
    ) -> Option<&ConversionRule> {
        self.conversion_rules.get(&(from_type, to_type))
    }

    /// 获取所有支持的转换
    pub fn get_supported_conversions(&self, from_type: MethodType) -> Vec<&ConversionRule> {
        self.conversion_rules
            .values()
            .filter(|rule| rule.from_type == from_type)
            .collect()
    }

    /// 中文数字转换
    fn chinese_to_number(s: &str) -> Result<Value, String> {
        let chinese_nums = [
            ("零", 0.0),
            ("一", 1.0),
            ("二", 2.0),
            ("三", 3.0),
            ("四", 4.0),
            ("五", 5.0),
            ("六", 6.0),
            ("七", 7.0),
            ("八", 8.0),
            ("九", 9.0),
            ("十", 10.0),
            ("百", 100.0),
            ("千", 1000.0),
            ("万", 10000.0),
            ("亿", 100000000.0),
            ("两", 2.0),
        ];

        for (chinese, num) in chinese_nums.iter() {
            if s == *chinese {
                return Ok(Value::number(*num));
            }
        }

        // 简单的复合中文数字转换
        if s == "十一" {
            return Ok(Value::number(11.0));
        }
        if s == "十二" {
            return Ok(Value::number(12.0));
        }
        if s == "二十" {
            return Ok(Value::number(20.0));
        }
        if s == "三十" {
            return Ok(Value::number(30.0));
        }
        if s == "一百" {
            return Ok(Value::number(100.0));
        }
        if s == "一千" {
            return Ok(Value::number(1000.0));
        }

        Err(format!("无法将字符串 '{}' 转换为数字", s))
    }

    /// 获取转换建议
    pub fn get_conversion_suggestions(
        &self,
        from_type: MethodType,
        to_type: MethodType,
    ) -> Vec<String> {
        let mut suggestions = Vec::new();

        if let Some(rule) = self
            .conversion_rules
            .get(&(from_type.clone(), to_type.clone()))
        {
            suggestions.push(rule.description.clone());

            if rule.allow_precision_loss {
                suggestions.push("注意：此转换可能导致精度损失".to_string());
            }

            if rule.conversion_type == ConversionType::Explicit {
                suggestions.push("此转换需要显式调用".to_string());
            }
        }

        // 提供替代方案
        match (from_type, to_type) {
            (MethodType::String, MethodType::Number) => {
                suggestions.push("确保字符串包含有效的数字格式".to_string());
                suggestions.push("支持中文数字转换".to_string());
            }
            (MethodType::List, MethodType::String) => {
                suggestions.push("列表将转换为字符串表示形式".to_string());
            }
            (MethodType::Dict, MethodType::String) => {
                suggestions.push("字典将转换为键值对字符串".to_string());
            }
            _ => {}
        }

        suggestions
    }
}

impl Default for TypeConverter {
    fn default() -> Self {
        Self::new()
    }
}

/// 类型转换工具函数
pub struct ConversionUtils;

impl ConversionUtils {
    /// 安全转换（尝试多种转换方式）
    pub fn safe_convert(
        converter: &TypeConverter,
        value: &Value,
        target_type: &MethodType,
    ) -> Result<Value, String> {
        // 首先尝试自动转换
        if let Ok(result) = converter.convert_automatically(value, &target_type) {
            return Ok(result);
        }

        // 然后尝试显式转换
        if let Ok(result) = converter.convert_explicitly(value, &target_type) {
            return Ok(result);
        }

        // 最后尝试自定义转换
        let converter_name = format!("{:?}_to_{:?}", value.get_type(), target_type.clone());
        if let Some(custom_converter) = converter.custom_converters.get(&converter_name) {
            return custom_converter(value);
        }

        Err(format!(
            "无法将类型 {:?} 安全转换为 {:?}",
            value.get_type(),
            target_type
        ))
    }

    /// 批量转换
    pub fn batch_convert(
        converter: &TypeConverter,
        values: &[Value],
        target_type: &MethodType,
    ) -> Result<Vec<Value>, String> {
        let mut results = Vec::new();

        for value in values {
            match Self::safe_convert(converter, value, target_type) {
                Ok(converted) => results.push(converted),
                Err(e) => return Err(e),
            }
        }

        Ok(results)
    }

    /// 检查转换兼容性
    pub fn check_conversion_compatibility(
        converter: &TypeConverter,
        from_type: &MethodType,
        to_type: &MethodType,
    ) -> ConversionCompatibility {
        if from_type == to_type {
            return ConversionCompatibility::Compatible;
        }

        if converter.supports_automatic_conversion(from_type, to_type) {
            ConversionCompatibility::Automatic
        } else if converter.supports_explicit_conversion(from_type, to_type) {
            ConversionCompatibility::Explicit
        } else {
            ConversionCompatibility::Incompatible
        }
    }
}

/// 转换兼容性枚举
#[derive(Debug, Clone, PartialEq)]
pub enum ConversionCompatibility {
    /// 完全兼容（类型相同）
    Compatible,
    /// 支持自动转换
    Automatic,
    /// 支持显式转换
    Explicit,
    /// 不兼容
    Incompatible,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_type_converter_creation() {
        let converter = TypeConverter::new();

        // 检查基本转换支持
        assert!(converter.supports_automatic_conversion(&MethodType::Number, &MethodType::String));
        assert!(converter.supports_automatic_conversion(&MethodType::Number, &MethodType::Boolean));
        assert!(converter.supports_automatic_conversion(&MethodType::Boolean, &MethodType::Number));
        assert!(converter.supports_automatic_conversion(&MethodType::Null, &MethodType::String));

        // 检查显式转换支持
        assert!(converter.supports_explicit_conversion(&MethodType::String, &MethodType::Number));
        assert!(converter.supports_explicit_conversion(&MethodType::List, &MethodType::String));
        assert!(converter.supports_explicit_conversion(&MethodType::Dict, &MethodType::String));
    }

    #[test]
    fn test_automatic_conversions() {
        let converter = TypeConverter::new();

        // 数字 -> 字符串
        let number = Value::number(42.5);
        let result = converter
            .convert_automatically(&number, &MethodType::String)
            .unwrap();
        assert_eq!(result.to_string(), "42.5");

        // 数字 -> 布尔值
        let number_true = Value::number(1.0);
        let number_false = Value::number(0.0);
        let result_true = converter
            .convert_automatically(&number_true, &MethodType::Boolean)
            .unwrap();
        let result_false = converter
            .convert_automatically(&number_false, &MethodType::Boolean)
            .unwrap();
        assert_eq!(result_true.to_string(), "真");
        assert_eq!(result_false.to_string(), "伪");

        // 布尔值 -> 数字
        let boolean_true = Value::boolean(true);
        let boolean_false = Value::boolean(false);
        let result_true = converter
            .convert_automatically(&boolean_true, &MethodType::Number)
            .unwrap();
        let result_false = converter
            .convert_automatically(&boolean_false, &MethodType::Number)
            .unwrap();
        assert_eq!(result_true.to_string(), "1");
        assert_eq!(result_false.to_string(), "0");

        // null -> 字符串
        let null_value = Value::null();
        let result = converter
            .convert_automatically(&null_value, &MethodType::String)
            .unwrap();
        assert_eq!(result.to_string(), "无");
    }

    #[test]
    fn test_explicit_conversions() {
        let converter = TypeConverter::new();

        // 字符串 -> 数字
        let string_num = Value::string("123.45".to_string());
        let result = converter
            .convert_explicitly(&string_num, &MethodType::Number)
            .unwrap();
        assert_eq!(result.to_string(), "123.45");

        // 中文数字转换
        let chinese_num = Value::string("一".to_string());
        let result = converter
            .convert_explicitly(&chinese_num, &MethodType::Number)
            .unwrap();
        assert_eq!(result.to_string(), "1");

        // 列表 -> 字符串
        let list = Value::list(vec![Value::number(1.0), Value::number(2.0)]);
        let result = converter
            .convert_explicitly(&list, &MethodType::String)
            .unwrap();
        assert_eq!(result.to_string(), "[1, 2]");
    }

    #[test]
    fn test_conversion_compatibility() {
        let converter = TypeConverter::new();

        // 检查兼容性
        assert_eq!(
            ConversionUtils::check_conversion_compatibility(
                &converter,
                &MethodType::Number,
                &MethodType::String
            ),
            ConversionCompatibility::Automatic
        );

        assert_eq!(
            ConversionUtils::check_conversion_compatibility(
                &converter,
                &MethodType::String,
                &MethodType::Number
            ),
            ConversionCompatibility::Explicit
        );

        assert_eq!(
            ConversionUtils::check_conversion_compatibility(
                &converter,
                &MethodType::Number,
                &MethodType::Number
            ),
            ConversionCompatibility::Compatible
        );
    }

    #[test]
    fn test_safe_convert() {
        let converter = TypeConverter::new();

        // 安全转换测试
        let number = Value::number(99.9);
        let result =
            ConversionUtils::safe_convert(&converter, &number, &MethodType::String).unwrap();
        assert_eq!(result.to_string(), "99.9");

        // 批量转换测试
        let values = vec![Value::number(1.0), Value::number(2.0), Value::number(3.0)];
        let results =
            ConversionUtils::batch_convert(&converter, &values, &MethodType::String).unwrap();
        assert_eq!(results.len(), 3);
        assert_eq!(results[0].to_string(), "1");
        assert_eq!(results[1].to_string(), "2");
        assert_eq!(results[2].to_string(), "3");
    }
}
